package com.hansen.library.ui.widget.progress;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.hansen.library.utils.ScreenSizeUtils;
import com.hansen.library.utils.StringUtils;

/**
 * 进度条
 * @author han
 * @date 2019/11/14
 */
public class HorizontalProgressBar extends View {

    private Context mContext;

    //进度条背景paint
    private Paint mProgressBkgPaint;
    //进度条paint
    private Paint mProgressPaint;

    private RectF mProgressBkgRectF = new RectF();
    private RectF mProgressRectF = new RectF();

    //最大进度值
    private float mMaxProgress = 100f;
    //进度值
    private float mProgress = 0f;
    //当前的进度值对应的with
    private float mCurrentProgressWidth = 0f;

    //进度动画
    private ValueAnimator mProgressAnimator;

    //动画执行时间
    private int mDuration = 650;
    //动画延时启动时间
    private int mStartDelay = 300;

    //宽度
    private int mWidth;
    //高度
    private int mHeight;
    //进度条画笔宽度
    private int mProgressWidth;
    //进度移动的距离
    private float mMoveDistance = 0f;

    //进度条背景颜色
    private int mBkgColor = 0xffeeeeee;
    //进度条颜色
    private int mProgressColor = 0xffff736a;

    private OnProgressListener onProgressListener;

    public HorizontalProgressBar(Context context) {
        this(context, null);
    }

    public HorizontalProgressBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HorizontalProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mContext = context;

        init(attrs);
    }

    private void init(AttributeSet attrs) {

        mProgressWidth = ScreenSizeUtils.dp2px(mContext, 10);

        mHeight = mProgressWidth;

        if(attrs != null) {

        }

        mProgressBkgPaint = getPaint(mProgressWidth, mBkgColor, Paint.Style.FILL);
        mProgressPaint = getPaint(mProgressWidth, mProgressColor, Paint.Style.FILL);

        if(isInEditMode()) {
            setCurrentProgress(50);
        }
    }

    /**
     * 统一处理paint
     *
     * @param strokeWidth
     * @param color
     * @param style
     * @return
     */
    private Paint getPaint(int strokeWidth, int color, Paint.Style style) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(strokeWidth);
        paint.setColor(color);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(style);
        return paint;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(measureWidth(widthMode, width), measureHeight(heightMode, height));
    }

    /**
     * 测量宽度
     *
     * @param mode
     * @param width
     * @return
     */
    private int measureWidth(int mode, int width) {
        switch (mode) {
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:
                break;
            case MeasureSpec.EXACTLY:
                mWidth = width;
                break;
        }
        return mWidth;
    }

    /**
     * 测量高度
     *
     * @param mode
     * @param height
     * @return
     */
    private int measureHeight(int mode, int height) {
        switch (mode) {
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:
                mHeight = mProgressWidth;
                break;
            case MeasureSpec.EXACTLY:
                mHeight = height;
                break;
        }
        return mHeight;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawBkgProgress(canvas);
        drawProgress(canvas);
    }

    private void drawBkgProgress(Canvas canvas) {
        mProgressBkgRectF.left = 0;
        mProgressBkgRectF.top = 0;
        mProgressBkgRectF.right = this.getMeasuredWidth();
        mProgressBkgRectF.bottom = mHeight;

        canvas.drawRoundRect(mProgressBkgRectF, mProgressWidth / 2, mProgressWidth / 2, mProgressBkgPaint);
    }

    private void drawProgress(Canvas canvas) {
        mProgressRectF.left = 0;
        mProgressRectF.top = 0;
        mProgressRectF.right = mCurrentProgressWidth;
        mProgressRectF.bottom = mHeight;

        canvas.drawRoundRect(mProgressRectF, mProgressWidth / 2, mProgressWidth / 2, mProgressPaint);
    }


    /**
     * 设置进度条带动画效果
     *
     * @param progress
     * @return
     */
    public HorizontalProgressBar setProgressWithAnimation(float progress) {
        mProgress = progress > mMaxProgress ? mMaxProgress : progress < 0 ? 0 : progress;

        mProgressAnimator = ValueAnimator.ofFloat(0, mProgress);
        mProgressAnimator.setDuration(mDuration);
        mProgressAnimator.setStartDelay(mStartDelay);
        mProgressAnimator.setInterpolator(new LinearInterpolator());
        mProgressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float value = (float) valueAnimator.getAnimatedValue();

                //把当前百分比进度转化成view宽度对应的比例
                mCurrentProgressWidth = value * mWidth / mMaxProgress;
                //进度回调方法
                if (onProgressListener != null) {
                    onProgressListener.currentProgressListener(value, mCurrentProgressWidth);
                }

                postInvalidate();
            }
        });

        post(new Runnable() {
            @Override
            public void run() {
                if (mProgressAnimator != null) {
                    mProgressAnimator.start();
                }
            }
        });

        return this;
    }

    public HorizontalProgressBar setCurrentProgress(String progress) {
        setCurrentProgress(StringUtils.getFloat(progress));
        return this;
    }

    /**
     * 实时显示进度
     *
     * @param progress
     * @return
     */
    public HorizontalProgressBar setCurrentProgress(float progress) {
        mProgress = progress > mMaxProgress ? mMaxProgress : progress < 0 ? 0 : progress;

        post(new Runnable() {
            @Override
            public void run() {
                mCurrentProgressWidth = mProgress * mWidth / mMaxProgress;

                if (onProgressListener != null) {
                    onProgressListener.currentProgressListener(mProgress, mCurrentProgressWidth);
                }

                invalidate();
            }
        });

        return this;
    }

    /**
     * 开启动画
     */
    public void startProgressAnimation() {
        if (mProgressAnimator != null &&
                !mProgressAnimator.isRunning() &&
                !mProgressAnimator.isStarted())
            mProgressAnimator.start();
    }

    /**
     * 暂停动画
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void pauseProgressAnimation() {
        if (mProgressAnimator != null) {
            mProgressAnimator.pause();
        }
    }

    /**
     * 恢复动画
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void resumeProgressAnimation() {
        if (mProgressAnimator != null)
            mProgressAnimator.resume();
    }

    /**
     * 停止动画
     */
    public void stopProgressAnimation() {
        if (mProgressAnimator != null) {
            mProgressAnimator.end();
        }
    }

    public void setOnProgressListener(OnProgressListener onProgressListener) {
        this.onProgressListener = onProgressListener;
    }

    /**
     * 回调接口
     */
    public interface OnProgressListener {
        void currentProgressListener(float progress, float currentWidth);
    }
}
